﻿using Core.Framework.Loger;
using Core.Framework.Model.Common;
using Core.Framework.Model.WebSockets;
using Core.Framework.Redis;
using Core.Framework.Redis.Queue_Helper;
using Core.Framework.Util;
using Core.IBusiness.ILoggerModule;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core.Middleware.WebSockets
{
    public class QueueMsg
    {

        /// <summary>
        /// 日志接口
        /// </summary>
        private ILog iLog = BuildServiceProvider.GetService<ILog>();

        public bool DoDispatch(QueryMessage model)
        {
            var msg = this.StructureMsg(model);

            if (msg == null)
                return false;

            RunningLogerInfoModel logerInfo = new RunningLogerInfoModel { TaskMessage = model, Message = msg };

            return this.TaskDistribution(model, logerInfo, msg);

        }

        /// <summary>
        /// 测试
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool DoDispatchTest(QueryMessageTest model)
        {

            #region 构造测试消息

            var msg = new MessageQueue
            {
                Template = model.Template,
                ClientInfo = new ClientInfo
                {
                    User = new UserInfo
                    {
                        Key = "test",
                        Parameter = new {
                            client = "ios",
                            headImg = "http://img5.duitang.com/uploads/item/201510/18/20151018121717_GVcJz.jpeg",
                            userName = "System"
                        }.TryToJson()
                    },
                    Project = new ProjectInfo
                    {
                        ProjectToken = model.ProjectToken,
                        CallUrl = model.CallUrl
                    }
                },
                Message = new Message
                {
                    Token = model.Token,
                    Content = model.Content,
                    MessageKey = model.MessageKey,
                    MessageType = model.MessageType,
                    Parameter = model.Parameter,
                    SendDateTime = model.SendDateTime
                }
            };

            #endregion

            if (msg == null)
                return false;

            RunningLogerInfoModel logerInfo = new RunningLogerInfoModel { TaskMessage = model.TryToJson().TryToEntity<QueryMessage>(), Message = msg };

            return this.TaskDistribution(logerInfo.TaskMessage, logerInfo, msg);

        }



        private MessageQueue StructureMsg(QueryMessage model)
        {

            // 根据token 获取登陆信息
            var result
                = RedisQueueHelper.HashGet(RedisQueueHelperParameter.WebSocketByToken, model.ClientToken);

            // 判断是否登陆
            if (!string.IsNullOrWhiteSpace(result))
            {
                var client = ((string)result).TryToEntity<ClientInfo>();

                return new MessageQueue
                {
                    Template = model.Template,
                    ClientInfo = new ClientInfo
                    {
                        User = new UserInfo
                        {
                            Key = client.User.Key,
                            Parameter = client.User.Parameter
                        },
                        Project = new ProjectInfo
                        {
                            ProjectToken = client.Project.ProjectToken,
                            CallUrl = client.Project.CallUrl
                        }
                    },
                    Message = new Message
                    {
                        Token = model.Token,
                        Content = model.Content,
                        MessageKey = model.MessageKey,
                        MessageType = model.MessageType,
                        Parameter = model.Parameter,
                        SendDateTime = model.SendDateTime
                    }
                };
            }

            return null;
        }

        
        /// <summary>
        /// 任务分发
        /// </summary>
        /// <param name="model"></param>
        /// <param name="logerInfo"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool TaskDistribution(QueryMessage model,RunningLogerInfoModel logerInfo, MessageQueue msg)
        {
            // 获取所有客户机
            var redis = new RedisHelper();
            var keys = redis.HashKeys(RedisQueueHelperParameter.QueueService);

            Dictionary<string, QueueService> dic
                = new Dictionary<string, QueueService>();

            // 构造服务列表
            foreach (var item in keys)
                dic.Add(item, redis.HashGet<QueueService>(RedisQueueHelperParameter.QueueService, item));

            Func<Listener_Template, bool> where = (a) =>
                (
                    a.template.ToLower() == model.Template.ToLower()
                    && a.Subscription != null
                    && a.Subscription.Contains(model.MessageKey)
                );

            // 筛选出符合条件的客户端
            var clients = dic.Where(a => a.Value.Temps.Where(where).FirstOrDefault() != null).ToArray();

            if (clients != null && clients.Count() > 0)
            {
                logerInfo.IsPublish = true;
                if (model.MessageType == MessageTypeEnum.Single)
                {
                    // 随机分配一个 客户端 [需要优化]
                    var i = new Random().Next(0, clients.Count() - 1);
                    redis.Publish(clients[i].Key, msg.TryToJson());
                    logerInfo.clients.Add(clients[i].Key);
                }

                else if (model.MessageType == MessageTypeEnum.Group)
                    foreach (var item in clients)
                    {
                        redis.Publish(item.Key, msg.TryToJson());
                        logerInfo.clients.Add(item.Key);
                    }
            }
            else
            {
                if (model.RetryCount >= model.MaxRetryCount)
                {
                    logerInfo.IsPublish = true;

                    if (model.MessageType == MessageTypeEnum.Single)
                        RedisQueueHelper
                            .ListPush(RedisQueueHelperParameter.SingleNull, msg.TryToJson());

                    RedisQueueHelper.ListPush(
                        RedisQueueHelperParameter.History,
                        msg.TryToJson());

                    iLog.Queue<QueueMsg>("暂无可用服务端，加入离线消息", "push_fail", model.Token);
                }
            }


            if (!logerInfo.IsPublish)
            {
                model.RetryCount++;
                RedisQueueHelper.SortedPush(
                    RedisQueueHelperParameter.UntreatedQueue,
                    model.TryToJson(), 1000 * model.DelaySeconds);
            }

            iLog.Queue<QueueMsg>(logerInfo.TryToJson(), model.RetryCount > 1 ? "retry" : "request", model.Token);

            return true;
        }
    }
}
